#include "MeshManager.h"
#include "..\Shared\ObjectTypes.h"

MeshManager::MeshManager(void)
{
}

MeshManager::~MeshManager(void)
{
}

MeshManager::MeshManager(const MeshManager &mm)
{
}

MeshManager* MeshManager::operator=(const MeshManager &mm)
{
	return this;
}

MeshManager* MeshManager::Instance()
{
	static MeshManager instance;

	return &instance;
}

////////////////////////////////////
// GetMesh()
//
// Returns the MeshData object being asked for
////////////////////////////////////
MeshData* MeshManager::GetMesh(ObjectType objectType)
{
	std::vector<MeshData*>::iterator i = meshData.begin();
	while (i != meshData.end())
	{
		if ((*i)->objectType == objectType)
			return *i;

		i++;
	}

	return NULL;
}

////////////////////////////////////
// GetBuffer()
//
// Returns the BufferData object being asked for
////////////////////////////////////
BufferData* MeshManager::GetBuffer(ObjectType objectType)
{
	std::vector<BufferData*>::iterator i = bufferData.begin();
	while (i != bufferData.end())
	{
		if ((*i)->objectType == objectType)
			return *i;

		i++;
	}

	return NULL;
}

////////////////////////////////////
// LoadMesh()
//
// Loads the mesh into the meshData structure
////////////////////////////////////
void MeshManager::LoadMesh(const std::string& filename, ObjectType objectType)
{
	// Create a new meshdata object
	MeshData* d = new MeshData;

	// we need a new mesh
	ID3DXMesh* mesh;

	// a list of materials
	std::vector<Mtrl> *materials = new std::vector<Mtrl>;

	// and a list of textures
	std::vector<IDirect3DTexture9*> *textures = new std::vector<IDirect3DTexture9*>;
	
	// load the mesh into these properties
	LoadXFile(filename, &mesh, *materials, *textures);

	// add the data into the MeshData
	d->mesh = mesh;
	d->materialList = materials;
	d->textureList = textures;
	d->objectType = objectType;

	// add the data to the vector
	meshData.push_back(d);
}

////////////////////////////////////
// LoadMesh()
//
// If we created our own specialized mesh, load it in
// with this method
////////////////////////////////////
void MeshManager::LoadMesh(ID3DXMesh* mesh, Mtrl mtrl, IDirect3DTexture9* texture, ObjectType objectType)
{
	MeshData* d = new MeshData;

	d->mesh = mesh;

	std::vector<Mtrl> *materials = new std::vector<Mtrl>;
	materials->push_back(mtrl);

	std::vector<IDirect3DTexture9*> *textures = new std::vector<IDirect3DTexture9*>;
	textures->push_back(texture);

	d->materialList = materials;
	d->textureList = textures;
	d->objectType = objectType;

	meshData.push_back(d);

}

////////////////////////////////////
// AddBuffer()
//
// Adds a pre-created buffer into the buffer list
////////////////////////////////////
void MeshManager::AddBuffer(IDirect3DVertexBuffer9* vbuffer, IDirect3DIndexBuffer9* ibuffer, Mtrl *mtrl, IDirect3DTexture9 *texture, ObjectType objectType)
{
	// create a new buffer data
	BufferData* b = new BufferData;
	
	// assign the info
	b->vbuffer = vbuffer;
	b->ibuffer = ibuffer;
	b->mtrl = mtrl;
	b->texture = texture;
	b->objectType = objectType;

	// add it to the list
	bufferData.push_back(b);
}

////////////////////////////////////
// ClearAll()
//
// Deletes all information. Should be called before the program shuts down.
////////////////////////////////////
void MeshManager::ClearAll(void)
{
	// go through the list of MeshDatas
	std::vector<MeshData*>::iterator i;
	while (meshData.size() > 0)
	{
		i = meshData.begin();
		
		// release the mesh
		(*i)->mesh->Release();

		// go through the list of textures
		std::vector<IDirect3DTexture9*>::iterator j;
		while ((*i)->textureList->size() > 0)
		{
			// release the texture and erase it from the list
			j = (*i)->textureList->begin();

			if ((*j) != 0) // texture could be null, so check first
			{
				(*j)->Release();
			}

			(*i)->textureList->erase(j);
		}

		// go through the list of materials
		std::vector<Mtrl>::iterator k;
		while ((*i)->materialList->size() > 0)
		{
			// erase it from the list (Mtrls are created on the stack,
			// so no need to delete
			k = (*i)->materialList->begin();
			(*i)->materialList->erase(k);
		}

		// delete the meshdata object (created on the heap)
		delete *i;

		// remove it from the list
		meshData.erase(i);
	}
}